package driver;

import java.util.Hashtable;

import driver.handlers.BasePersonTypeHandler;
import driver.handlers.BasicHandler;

import state.group.events.BaseEvent;
import state.person.Person;
import state.person.PersonType;
import system.GlobalData;

/**
 * This is the main Person Driver handler.
 * Singleton Class
 * 
 * @author Ian Doerr
 */
public final class PersonDriver {
    
    private static PersonDriver instance;
    
    /**
     * Initializes the instance of the PersonDriver
     */
    public static void init()
    {
        instance = new PersonDriver();
    }
    
    /**
     * Returns the instance of the PersonDriver
     * 
     * @return
     */
    public static PersonDriver getInstance()
    {
        return instance;
    }
    
    private Hashtable<PersonType, BasePersonTypeHandler> handlers;
    
    /**
     * Initializes the mappings for People and their handlers.
     */
    private PersonDriver()
    {
        handlers = new Hashtable<PersonType, BasePersonTypeHandler>();
        
        handlers.put(PersonType.Basic, new BasicHandler());
    }
    
    /**
     * handles an event, by iterating over the people collection, and identifying
     * events that trigger actions by people.
     * 
     * @param event
     */
    public void handleEvent(BaseEvent event)
    {
        synchronized (GlobalData.state.activePeople)
        {
            for (Person p : GlobalData.state.activePeople)
            {
                synchronized (p)
                {
                    if (!p.isFree())
                    {
                        continue;
                    }
            
                    BasePersonTypeHandler handler = handlers.get(p.getType());
                    
                    if (handler == null)
                    {
                        throw new RuntimeException("Person had an unrecognized type: " + p.getType());
                    }
                    
                    switch (event.getEventType())
                    {                    
                        case DoorEvent:
                        case FloorEvent:
                        case StopEvent:
                            handler.handleEvent(event, p);
                    }
                }
            }
        }
    }
    
    /**
     * Handles the creation event for a person.
     * 
     * @param p
     */
    public void doCreation(Person p)
    {
        BasePersonTypeHandler handler = handlers.get(p.getType());
        
        if (handler == null)
        {
            throw new RuntimeException("Person had an unrecognized type: " + p.getType());
        }
        
        handler.handleCreation(p);
    }
    
}
